package com.ruiyou.ub;

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.camera.core.ImageProxy;
import androidx.core.content.ContextCompat;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

enum DialogType {
    INFO, CONFIRM, EDIT, SELECT
}

public class Util {
    public static String decodeQRCode(@NonNull Object obj) {
        int[] pixels;
        int w, h;
        if (obj instanceof Bitmap) {
            Bitmap bmp = (Bitmap) obj;
            w = bmp.getWidth();
            h = bmp.getHeight();
            pixels = new int[w * h];
            bmp.getPixels(pixels, 0, w, 0, 0, w, h);
        } else if (obj instanceof ImageProxy) {
            ImageProxy img = (ImageProxy) obj;
            w = img.getWidth();
            h = img.getHeight();
            ByteBuffer buffer = img.getPlanes()[0].getBuffer();
            buffer.rewind();
            byte[] bs = new byte[buffer.remaining()];
            buffer.get(bs);
            pixels = new int[bs.length];
            for (int i = 0; i < bs.length; i++) {
                pixels[i] = bs[i] & 0xFF;
            }
        } else {
            return null;
        }
        BinaryBitmap binaryBitmap = new BinaryBitmap(
                new GlobalHistogramBinarizer(
                        new RGBLuminanceSource(w, h, pixels)
                )
        );
        Map<DecodeHintType, Object> hints = new HashMap<>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        try {
            return new MultiFormatReader().decode(binaryBitmap, hints).toString();
        } catch (NotFoundException e) {
            BinaryBitmap binaryBitmap1 = new BinaryBitmap(
                    new HybridBinarizer(
                            new RGBLuminanceSource(w, h, pixels)
                    )
            );
            try {
                return new MultiFormatReader().decode(binaryBitmap1, hints).toString();
            } catch (NotFoundException ignore) {
            }
        }
        return null;
    }

    static void showDialog(
            Context context,
            String title,
            String content,
            DialogType type,
            Callback callback
    ) {
        TextView titleView = new TextView(
                context, null, 0, R.style.TextViewStyle
        );
        titleView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24);
        titleView.setText(title);
        titleView.setBackgroundColor(
                ContextCompat.getColor(context, R.color.primary_light_color)
        );
        titleView.setTypeface(Typeface.DEFAULT_BOLD);
        titleView.setGravity(Gravity.CENTER_HORIZONTAL);
        Builder builder = new Builder(context).setCustomTitle(titleView);
        setContent(context, builder, content, type, callback);
        builder.create().show();
    }

    private static void setContent(
            Context context,
            Builder builder,
            String content,
            DialogType type,
            Callback callback
    ) {
        if (type == DialogType.SELECT) {
            String[] items = content.split(",");
            int[] sel = {0};
            builder.setSingleChoiceItems(
                    items, 0, (dialog, which) -> sel[0] = which
            );
            builder.setPositiveButton(
                    android.R.string.ok,
                    (dialog, which) -> callback.onCallback(String.valueOf(sel[0]))
            );
            builder.setNegativeButton(android.R.string.cancel, null);
            return;
        }
        // ===============================
        View rootView = LayoutInflater.from(context)
                .inflate(R.layout.dialog, null);
        TextView textView = rootView.findViewById(R.id.dialog_text);
        textView.setText(content);
        builder.setView(rootView);
        EditText editText = rootView.findViewById(R.id.dialog_edit);
        if (type == DialogType.EDIT) {
            editText.setVisibility(View.VISIBLE);
            editText.setOnEditorActionListener((v, actionId, event) -> {
                InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(textView.getWindowToken(), 0);
                return true;
            });
        }
        DialogInterface.OnClickListener listener = null;
        if (type != DialogType.INFO) {
            listener = (dialog, which) -> callback.onCallback(
                    type == DialogType.EDIT ?
                            editText.getText().toString().trim() : null
            );
            builder.setNegativeButton(android.R.string.cancel, null);
        }
        builder.setPositiveButton(android.R.string.ok, listener);
    }

    public interface Callback {
        void onCallback(String result);
    }
}
